/*
 * Copyright 2008-2010 Daniel Cachapa <cachapa@gmail.com>
 * 
 * This program is distributed under the terms of the GNU General Public License Version 3
 * The license can be read in its entirety in the LICENSE.txt file accompanying this source code,
 * or at: http://www.gnu.org/copyleft/gpl.html
 * 
 * This file is part of Libra.
 *
 * WeightWatch is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 *
 * WeightWatch is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with the WeightWatch source code. If not, see: http://www.gnu.org/licenses
 */

package net.cachapa.libra;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import net.cachapa.libra.R;
import net.cachapa.libra.component.ValueSelector;
import net.cachapa.libra.component.ValueSelector.OnValueChangedListener;
import net.cachapa.libra.dailyburn.DailyBurnApi;
import net.cachapa.libra.data.Database;
import net.cachapa.libra.data.Value;
import net.cachapa.libra.util.Bmi;
import net.cachapa.libra.util.ProMode;
import net.cachapa.libra.util.UnitManager;
import net.cachapa.libra.util.Util;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ActivityNotFoundException;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.net.Uri;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.Preference.OnPreferenceClickListener;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class Preferences extends PreferenceActivity implements OnPreferenceClickListener, OnPreferenceChangeListener {
	public static final String AUTO_SYNC = "autoSyncPreference";
	public static final String HEIGHT = "heightPreference";
	public static final String GOAL_WEIGHT = "goalWeightPreference";
	public static final String HEIGHT_UNITS = "heightUnitsPreference";
	public static final String WEIGHT_UNITS = "weightUnitsPreference";
	public static final String SHOW_GOAL = "showGoalPreference";
	public static final String SHOW_BMI_LINES = "showBmiLinesPreference";
	public static final String SHOW_EXPECTED_LINE = "showExpectedLinePreference";
	public static final String SHOW_EXPECTED_DATE = "showExpectedDatePreference";
	public static final String VERSION = "versionPreference";
	public static final String CHART_TYPE = "chartTypePreference";
	public static final String AUTO_BACKUP = "autoBackupPreference";
	public static final String LAST_BACKUP_DATE = "lastBackupDatePreference";
	
	private static final int DIALOG_HEIGHT = 0;
	private static final int DIALOG_GOAL_WEIGHT = 1;
	private static final int DIALOG_CHANGELOG = 2;
	
	private UnitManager um;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		if (ProMode.isInProMode(this)) {
			addPreferencesFromResource(R.xml.preferences);
		}
		else {
			addPreferencesFromResource(R.xml.preferences_ad);
		}
		this.um = UnitManager.getInstance(this);
		
		// React to the preferences
		Preference heightUnitsPref = (Preference) findPreference(HEIGHT_UNITS);
		heightUnitsPref.setOnPreferenceChangeListener(this);
		
		Preference weightUnitsPref = (Preference) findPreference(WEIGHT_UNITS);
		weightUnitsPref.setOnPreferenceChangeListener(this);
		
		Preference heightPref = (Preference) findPreference(HEIGHT);
		heightPref.setOnPreferenceClickListener(this);
		
		Preference goalWeightPref = (Preference) findPreference(GOAL_WEIGHT);
		goalWeightPref.setOnPreferenceClickListener(this);
		
		Preference databasePref = (Preference) findPreference("databasePreference");
		databasePref.setIntent(new Intent(this, net.cachapa.libra.DatabaseList.class));
		
		Preference logInPref = (Preference) findPreference("logInPreference");
		logInPref.setOnPreferenceClickListener(this);
		
		Preference disableAdsPref = (Preference) findPreference("disableAdsPreference");
		if (!ProMode.isInProMode(this)) {
			disableAdsPref.setOnPreferenceClickListener(this);
		}
		
		Preference helpPref = (Preference) findPreference("helpPreference");
		helpPref.setIntent(new Intent(this, net.cachapa.libra.Help.class));
		
		Preference changelogPref = (Preference) findPreference("changelogPreference");
		changelogPref.setOnPreferenceClickListener(this);
		
		Preference contactDeveloperPref = (Preference) findPreference("contactDeveloperPreference");
		contactDeveloperPref.setOnPreferenceClickListener(this);
		
		Preference aboutPref = (Preference) findPreference("aboutPreference");
		aboutPref.setIntent(new Intent(this, net.cachapa.libra.About.class));
	}
	
	@Override
	protected void onResume() {
		super.onResume();
		updateSummaries();
	}

	private void updateSummaries() {
		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
		Preference item;
		
		float height = prefs.getFloat(HEIGHT, 0);
		if (height > 0) {
			item = (Preference) findPreference(HEIGHT);
			item.setSummary(um.toHeightUnit(height));
		}
		
		float goalWeight = prefs.getFloat(GOAL_WEIGHT, 0);
		if (goalWeight > 0) {
			item = (Preference) findPreference(GOAL_WEIGHT);
			item.setSummary(um.toWeightUnit(goalWeight));
			// Enable the show goal pref
			item = (Preference) findPreference(SHOW_GOAL);
			item.setEnabled(true);
			// Enable the expected date pref
			item = (Preference) findPreference(SHOW_EXPECTED_DATE);
			item.setEnabled(true);
		}
		
		item = (Preference) findPreference(HEIGHT_UNITS);
		if (um.isMetricHeight()) {
			item.setSummary(R.string.meters);
		}
		else {
			item.setSummary(R.string.feet);
		}
		
		item = (Preference) findPreference(WEIGHT_UNITS);
		if (um.isMetricWeight()) {
			item.setSummary(R.string.kilograms);
		}
		else if (um.isStones()) {
			item.setSummary(R.string.stones);
		}
		else {
			item.setSummary(R.string.pounds);
		}
		
		Database database = Database.getInstance(this);
		int databaseSize = database.getSize();
		String databaseText;
		switch (databaseSize) {
		case 0:
			databaseText = getString(R.string.database_empty);
			break;
		case 1:
			databaseText = getString(R.string.database_one_entry);
			break;
		default:
			databaseText = String.format(getString(R.string.database_many_entries), databaseSize);
			break;
		}
		item = (Preference) findPreference("databasePreference");
		item.setSummary(databaseText);
		
		Preference logInItem = (Preference) findPreference("logInPreference");
		Preference autoSyncItem = (Preference) findPreference(AUTO_SYNC);
		if (DailyBurnApi.getInstance(this).isLoggedIn()) {
			logInItem.setTitle(R.string.log_out);
			logInItem.setSummary(R.string.logged_in);
			// Enable the auto sync pref
			autoSyncItem.setEnabled(true);
		}
		else {
			logInItem.setTitle(R.string.log_in);
			logInItem.setSummary(null);
			// Disable the auto sync pref
			autoSyncItem.setEnabled(false);
		}
	}

	public boolean onPreferenceClick(Preference preference) {
		if (preference.getKey().equals(HEIGHT)) {
			generateHeightDialog().show();
		}
		
		else if (preference.getKey().equals(GOAL_WEIGHT)) {
			generateGoalWeightDialog().show();
		}
		
		else if (preference.getKey().equals("logInPreference")) {
			DailyBurnApi dailyBurnApi = DailyBurnApi.getInstance(this);
			if (dailyBurnApi.isLoggedIn()) {
				dailyBurnApi.logout();
			}
			else {
				try {
					DailyBurnApi.getInstance(this).login();
				} catch (Exception e) {
					Toast.makeText(this, e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
					e.printStackTrace();
				}
			}
			updateSummaries();
		}
		
		else if (preference.getKey().equals("changelogPreference")) {
			showDialog(DIALOG_CHANGELOG);
		}
		
		else if (preference.getKey().equals("disableAdsPreference")) {
			final Intent marketIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + ProMode.PRO_PLUGIN)); 
			try {
				startActivity(marketIntent);
			} catch (ActivityNotFoundException e) {
				Toast.makeText(this, R.string.error_market, Toast.LENGTH_LONG).show();
			}
		}
		
		else if (preference.getKey().equals("contactDeveloperPreference")) {
			final Intent emailIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("mailto:cachapa@gmail.com")); 
			try {
				startActivity(emailIntent);
			} catch (ActivityNotFoundException e) {
				Toast.makeText(this, R.string.error_email, Toast.LENGTH_LONG).show();
			}
		}

		return false;
	}
	
	public boolean onPreferenceChange(Preference preference, Object newValue) {
		if (preference.getKey().equals(HEIGHT_UNITS)) {
			um.setMetricHeight(newValue.equals("meters"));
			updateSummaries();
		}
		
		else if (preference.getKey().equals(WEIGHT_UNITS)) {
			um.setMetricWeight(newValue.equals("kilograms"));
			um.setStones(newValue.equals("stones"));
			updateSummaries();
		}
		
		return true;
	}

	@Override
	protected Dialog onCreateDialog(int id) {
		switch (id) {
		case DIALOG_HEIGHT:
			return generateHeightDialog();
			
		case DIALOG_GOAL_WEIGHT:
			return generateGoalWeightDialog();
			
		case DIALOG_CHANGELOG:
			StringBuilder changelog = new StringBuilder();
			BufferedReader input;
			try {
				InputStream is = getResources().openRawResource(R.raw.changelog);
				input = new BufferedReader(new InputStreamReader(is));
				String line;
				while ((line = input.readLine()) != null) {
					changelog.append(line);
					changelog.append("<br/>");
				}
				input.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			
			return new AlertDialog.Builder(this)
			.setTitle(R.string.changelog_title)
			.setMessage(Html.fromHtml(changelog.toString()))
			.setPositiveButton(R.string.close, null)
			.create();
		}
		return null;
	}
	
	private AlertDialog generateHeightDialog() {
		final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
		final Editor prefsEditor = prefs.edit();
		
		LayoutInflater heightInflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
		View heightLayout = heightInflater.inflate(R.layout.heightdialog, null);
		
		int decimalPlaces = 2;
		if (!um.isMetricHeight()) {
			decimalPlaces = 0;
		}
		final ValueSelector heightSelector = (ValueSelector) heightLayout.findViewById(R.id.HeightValueSelector);
		heightSelector.initialize(um.getMinHeight(), um.getMaxHeight(), decimalPlaces, ValueSelector.TYPE_HEIGHT);
		float initialHeight = prefs.getFloat(HEIGHT, um.getDefaultHeight());
		heightSelector.setValue(initialHeight);
		
		return new AlertDialog.Builder(this)
			.setTitle(R.string.height)
			.setView(heightLayout)
			.setPositiveButton(android.R.string.ok,new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int whichButton) {
					prefsEditor.putFloat(HEIGHT, heightSelector.getValue());
					prefsEditor.commit();
					updateSummaries();
				}
			})
			.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog,	int whichButton) {
				}
			}).create();
	}
	
	private AlertDialog generateGoalWeightDialog() {
		final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
		final Editor prefsEditor = prefs.edit();
		final float height = prefs.getFloat(HEIGHT, 0);
		Database database = Database.getInstance(this);
		final Value latestValue = database.getLatestValue();
		
		LayoutInflater goalWeightInflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
		final View goalWeightLayout = goalWeightInflater.inflate(R.layout.goalweightdialog, null);
		final ValueSelector goalWeightSelector = (ValueSelector) goalWeightLayout.findViewById(R.id.GoalWeightValueSelector);
		goalWeightSelector.initialize(um.getMinWeight(), um.getMaxWeight(), 1, ValueSelector.TYPE_WEIGHT);
		
		// Initial value
		float initialGoalWeight = prefs.getFloat(GOAL_WEIGHT, 0);
		if (initialGoalWeight == 0) {
			if (height != 0) {
				initialGoalWeight = (float) Bmi.getIdealWeight(height, um.isMetricHeight(), um.isMetricWeight());
			}
			else {
				initialGoalWeight = um.getDefaultWeight();
			}
		}
		
		goalWeightSelector.setOnValueChangedListener(new OnValueChangedListener() {
			public void valueChanged(float newValue) {
				// Bmi
				String bmiLabel;
				if (height > 0) {
					bmiLabel = Util.Round(Bmi.calculateBMI(newValue, height, um.isMetricHeight(), um.isMetricWeight()), 1) + "";
				}
				else {
					bmiLabel = getString(R.string.not_available);
				}
				TextView bmiTextView = (TextView) goalWeightLayout.findViewById(R.id.BmiTextView);
				bmiTextView.setText(bmiLabel);
				
				// Change
				String changeLabel;
				String positiveSign = "";
				if (latestValue != null) {
					float change = newValue - latestValue.getTrend();
					if (change > 0) {
						positiveSign = "+";
					}
					changeLabel = positiveSign + um.toWeightUnit(change);
				}
				else {
					changeLabel = getString(R.string.not_available);
				}
				TextView changeTextView = (TextView) goalWeightLayout.findViewById(R.id.ChangeTextView);
				changeTextView.setText(changeLabel);
				Database.sendUpdateIntent(getBaseContext());
			}
		});
		
		goalWeightSelector.setValue(initialGoalWeight);
		
		return new AlertDialog.Builder(this)
        	.setTitle(R.string.goal_weight_title)
        	.setView(goalWeightLayout)
        	.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
        		public void onClick(DialogInterface dialog, int whichButton) {
					prefsEditor.putFloat(GOAL_WEIGHT, goalWeightSelector.getValue());
					prefsEditor.commit();
					updateSummaries();
        		}
        	})
        	.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
        		public void onClick(DialogInterface dialog, int whichButton) {
        		}
        	})
        	.create();
	}
}